home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / utility1 / gsview08.zip / GSVIEW.C < prev    next >
C/C++ Source or Header  |  1993-07-06  |  34KB  |  1,203 lines

  1. /*
  2.  * gsview.c -- Main module of GSVIEW.EXE, a graphical interface for 
  3.  *             MS-Windows Ghostscript
  4.  * Copyright (C) 1993  Russell Lang
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *   Author: Russell Lang
  21.  * Internet: rjl@monu1.cc.monash.edu.au
  22.  */
  23.  
  24. #define STRICT
  25. #include <windows.h>
  26. #include <windowsx.h>
  27. #include <commdlg.h>
  28. #include <shellapi.h>
  29. #include <mmsystem.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <ctype.h>
  34. #include <dir.h>
  35. #include <io.h>
  36. #define NeedFunctionPrototypes 1
  37. #include "ps.h"
  38. #include "gsview.h"
  39.  
  40. char szAppName[MAXSTR];            /* application name - for title bar */
  41. const char szClassName[] = "gsview_class";
  42. const char szScratch[] = "gsview";    /* temporary filename prefix */
  43.  
  44. HWND hwndimg;            /* gsview main window */
  45. HWND hDlgModeless;        /* any modeless dialog box */
  46. HWND hwndtext;            /* gswin text window */
  47. HWND hwndimgchild;        /* gswin image child window */
  48. HINSTANCE phInstance;        /* instance of gsview */
  49. HINSTANCE gswin_hinst;        /* instance of gswin */
  50. int bitmap_scrollx=0;        /* offset from bitmap to origin of child window */
  51. int bitmap_scrolly=0;
  52. int bitmap_width;        /* size of gswin bitmap in pixels */
  53. int bitmap_height;
  54.  
  55. /* these can be saved in the INI file */
  56. char szGSwin[128];        /* command to invoke gswin */
  57. POINT img_origin;        /* gsview window origin */
  58. POINT img_size;            /* gsview window size */
  59. BOOL quick;            /* use quick opening (don't reload gswin) */
  60. BOOL settings;            /* save settings on exit */
  61. BOOL button_show;        /* show buttons bar */
  62. int media;            /* IDM_LETTER etc. */
  63. int user_width, user_height;    /* User Defined media size */
  64. BOOL epsf_clip;            /* make bitmap size of epsf bounding box */
  65. BOOL epsf_warn;            /* write warning messages if operators incompatible with EPS are used */
  66. BOOL redisplay;            /* redisplay on resize */
  67. int orientation;        /* IDM_PORTRAIT, IDM_LANDSCAPE etc. */
  68. BOOL swap_landscape;        /* swap IDM_LANDSCAPE & IDM_SEASCAPE */
  69. float xdpi, ydpi;        /* resolution of gswin bitmap */
  70. UINT timeout;            /* default timeout period in 1 sec units */
  71. BOOL save_dir;            /* remember current directory for next time */
  72. char device_name[32];        /* printer name */
  73. char device_resolution[32];    /* printer resolution */
  74.  
  75. struct sound_s sound[NUMSOUND] = {
  76.     {"SoundOutputPage", IDS_SNDPAGE, ""},
  77.     {"SoundNoPage", IDS_SNDNOPAGE, BEEP},
  78.     {"SoundNoNumbering", IDS_SNDNONUMBER, ""},
  79.     {"SoundNotOpen", IDS_SNDNOTOPEN, ""},
  80.     {"SoundError", IDS_SNDERROR, BEEP},
  81.     {"SoundTimeout", IDS_SNDTIMEOUT, ""},
  82.     {"SoundStart", IDS_SNDSTART, ""},
  83.     {"SoundExit", IDS_SNDEXIT, ""},
  84. };
  85.  
  86.  
  87. /* initialised in init.c */
  88. BOOL is_win31 = FALSE;        /* To allow selective use of win 3.1 features */
  89. char szHelpName[MAXSTR];    /* buffer for building help filename */
  90. char szHelpTopic[48];        /* topic for OFN_SHOWHELP */
  91. UINT help_message;        /* message sent by OFN_SHOWHELP */
  92. HMENU hmenu;            /* main menu */
  93. HACCEL haccel;            /* menu accelerators */
  94. HCURSOR hcWait;
  95. POINT img_offset;        /* offset to gswin child window */
  96. POINT info_file;        /* position of file information */
  97. POINT info_page;        /* position of page information */
  98. RECT  info_rect;        /* position and size of brief info area */
  99. RECT  info_coord;        /* position and size of coordinate information */
  100. RECT  button_rect;        /* position and size of button area */
  101.  
  102. BOOL prev_in_child;        /* true if cursor previously in gswin child window */
  103. BOOL waiting = FALSE;        /* true when 'wait' to be displayed in info area */
  104. BOOL page_ready = FALSE;    /* true when gswin has sent an OUTPUT_PAGE and is waiting for NEXT_PAGE */
  105. BOOL saved = FALSE;        /* true if interpreter state currently saved in /gssave */
  106. BOOL epsf_clipped;        /* clipping this page? */
  107. int page_skip = 5;        /* number of pages to skip in IDM_NEXTSKIP or IDM_PREVSKIP */
  108. BOOL debug = FALSE;        /* /D command line option used */
  109. HINSTANCE hlib_mmsystem;    /* DLL containing sndPlaySound function */
  110. FPSPS lpfnSndPlaySound;        /* pointer to sndPlaySound function if loaded */
  111.  
  112. /* timer used for open, close, display & print timeouts */
  113. BOOL bTimeout;            /* true if timeout occured */
  114. BOOL bTimerSet;            /* true if TIMER running */
  115. #define ID_MYTIMER 1
  116. UINT timeout_count;
  117.  
  118. /* document manipulation */
  119. struct document *doc;    /* DSC structure.  NULL if not DSC */
  120. int pagenum;        /* current page number */
  121. char dfname[MAXSTR];    /* name of selected document file */
  122. char efname[MAXSTR];    /* name of temporary file containing PS extracted 
  123.                            from DOS EPS file */
  124. FILE *dfile;        /* selected file */
  125. FILE *cfile;        /* command file (pipe) */
  126. BOOL is_ctrld;        /* TRUE if DSC except for ctrl+D at start of file */
  127. int preview;        /* preview type IDS_EPSF, IDS_EPSI, etc. */
  128. struct page_list_s page_list;    /*  page selection for print/extract */
  129.  
  130. /* local functions */
  131. BOOL draw_button(DRAWITEMSTRUCT FAR *lpdis);
  132. BOOL in_child_client_area(void);
  133. BOOL in_client_area(void);
  134. BOOL in_info_area(void);
  135. void info_paint(HWND);
  136. void gsview_close(void);
  137. int gsview_command(WORD);
  138. BOOL not_open(void);
  139. BOOL not_dsc(void);
  140.  
  141. int PASCAL 
  142. WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow)
  143. {
  144.     MSG msg;
  145.  
  146.     /* copy the hInstance into a variable so it can be used */
  147.     phInstance = hInstance;
  148.  
  149.     LoadString(hInstance, IDS_TITLE, szAppName, sizeof(szAppName));
  150.     if (hPrevInstance) {
  151.         /* don't run more than one copy */
  152.         /* because we can't run more than one Ghostscript */
  153.         gsview_init0(lpszCmdLine);
  154.         return FALSE;
  155.     }
  156.  
  157.     gsview_init1(lpszCmdLine);
  158.     ShowWindow(hwndimg, cmdShow);
  159.     
  160.     while (GetMessage(&msg, (HWND)NULL, 0, 0)) {
  161.         if ((hDlgModeless == 0) || !IsDialogMessage(hDlgModeless, &msg)) {
  162.             if (!TranslateAccelerator(hwndimg, haccel, &msg)) {
  163.             TranslateMessage(&msg);
  164.             DispatchMessage(&msg);
  165.             }
  166.         }
  167.     }
  168.  
  169.     play_sound(SOUND_EXIT);
  170.     gsview_close();
  171.      WinHelp(hwndimg,szHelpName,HELP_QUIT,(DWORD)NULL);
  172.     if (is_win31 && (hlib_mmsystem != (HINSTANCE)NULL))
  173.         FreeLibrary(hlib_mmsystem);
  174.     return 0;
  175. }
  176.  
  177.  
  178. /* parent overlapped window */
  179. LRESULT CALLBACK _export
  180. WndImgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  181. {
  182. RECT rect;
  183.  
  184.     if (message == WM_GSVIEW) {
  185.     switch(wParam) {
  186.         case HWND_TEXT:
  187.         /* lParam = handle to Ghostscript Borland EasyWin window */
  188.         hwndtext = (HWND)lParam;
  189.         break;
  190.         case HWND_IMGCHILD:
  191.         /* lParam = handle to Ghostscript image child window */
  192.         hwndimgchild = (HWND)lParam;
  193.         if (hwndimgchild && IsWindow(hwndimgchild)) {
  194.             SetClassCursor(hwndimgchild, LoadCursor((HINSTANCE)NULL, IDC_CROSS));
  195.             GetClientRect(hwnd, &rect);
  196.             SetWindowPos(hwndimgchild, (HWND)NULL, rect.left+img_offset.x, rect.top+img_offset.y,
  197.             rect.right-img_offset.x, rect.bottom-img_offset.y, 
  198.             SWP_NOZORDER | SWP_NOACTIVATE);
  199.         }
  200.         break;
  201.         case GSWIN_CLOSE:
  202.         /* something is closing gswin */
  203.         gswin_hinst = (HINSTANCE)NULL;
  204.         hwndimgchild = (HWND)NULL;
  205.         hwndtext = (HWND)NULL;
  206.         bitmap_scrollx = bitmap_scrolly = 0;
  207.         page_ready = FALSE;
  208.         saved = FALSE;
  209.         pipeclose();
  210.         clear_timer();
  211.         info_wait(FALSE);
  212.         break;
  213.         case OUTPUT_PAGE:
  214.         /* showpage has just been called */
  215.         clear_timer();
  216.         play_sound(SOUND_PAGE);
  217.         if (IsIconic(hwndimg))    /* useless as an Icon so fix it */
  218.             ShowWindow(hwndimg, SW_SHOWNORMAL);
  219.         if ( !IsIconic(hwndimg) ) {  /* redraw child window */
  220.             if (hwndimgchild && IsWindow(hwndimgchild)) {
  221.             /* don't erase background - the bitmap will cover it anyway */
  222.             InvalidateRect(hwndimgchild, (LPRECT)NULL, FALSE);
  223.             UpdateWindow(hwndimgchild);
  224.             }
  225.         }
  226.         page_ready = TRUE;
  227.         info_wait(FALSE);
  228.         break;
  229.         case SYNC_OUTPUT:
  230.         /* time to redraw window */
  231.         if ( !IsIconic(hwndimg) ) {  /* redraw child window */
  232.             if (hwndimgchild && IsWindow(hwndimgchild)) {
  233.             /* don't erase background - the bitmap will cover it anyway */
  234.             InvalidateRect(hwndimgchild, (LPRECT)NULL, FALSE);
  235.             UpdateWindow(hwndimgchild);
  236.             }
  237.         }
  238.         break;
  239.         case SCROLL_POSITION:
  240.         /* User scrolled image window.  
  241.          * lParam = offsets to top left of image window
  242.          * we use these to display coordinates */
  243.         bitmap_scrollx = LOWORD(lParam);
  244.         bitmap_scrolly = HIWORD(lParam);
  245.         InvalidateRect(hwndimg, &info_coord, FALSE);
  246.         UpdateWindow(hwndimg);
  247.         break;
  248.         case PIPE_REQUEST:
  249.         piperequest();
  250.         break;
  251.         default:
  252.         gserror(0, "Unknown Message", MB_ICONEXCLAMATION, -1);
  253.     }
  254.     return 0;
  255.     }
  256.     else if (message == help_message) {
  257.     WinHelp(hwndimg,szHelpName,HELP_KEY,(DWORD)szHelpTopic);
  258.     return 0;
  259.     } else
  260.     switch(message) {
  261.     case WM_CREATE:
  262.         hwndimg = hwnd;
  263.         gsview_create();
  264.         /* Enable Drag Drop */
  265.         if (is_win31)
  266.             DragAcceptFiles(hwnd, TRUE);
  267.         break;
  268.     case WM_DESTROY:
  269.         /* disable Drag Drop */
  270.         if (is_win31)
  271.             DragAcceptFiles(hwnd, FALSE);
  272.         gsview_close();
  273.         PostQuitMessage(0);
  274.         break;
  275.     case WM_ENDSESSION:
  276.         if (wParam)
  277.             gsview_close();
  278.         return 0;
  279.     case WM_TIMER:
  280.         if (wParam == ID_MYTIMER) {
  281.             timeout_count--;
  282.             if (timeout_count <= 0) {
  283.             clear_timer();
  284.             bTimeout = TRUE;
  285.             gserror(IDS_TIMEOUT, NULL, MB_ICONINFORMATION, SOUND_TIMEOUT);
  286.             info_wait(FALSE);
  287.             }
  288.         }
  289.         break;
  290.     case WM_DROPFILES:
  291.         if (is_win31) {
  292.             LPSTR szFile;
  293.             int i, cFiles, length;
  294.             HDROP hdrop = (HDROP)wParam;
  295.             cFiles = DragQueryFile(hdrop, 0xffff, (LPSTR)NULL, 0);
  296.             for (i=0; i<cFiles; i++) {
  297.             length = DragQueryFile(hdrop, i, (LPSTR)NULL, 0);
  298.             szFile = GlobalAllocPtr(GHND, length+1);
  299.             if (szFile) {
  300.                 DragQueryFile(hdrop, i, szFile, MAXSTR);
  301.                 /* it doesn't work if we call gsview_display directly */
  302.                 PostMessage(hwnd, WM_COMMAND, IDM_DROP, (LPARAM)szFile);
  303.             }
  304.             }
  305.             DragFinish(hdrop);
  306.         }
  307.         break;
  308.     case WM_INITMENU:
  309.         if (hmenu == (HMENU)wParam) {
  310.             HMENU hmenuedit = GetSubMenu(hmenu,1);
  311.             if (hwndimgchild  && IsWindow(hwndimgchild))
  312.             EnableMenuItem(hmenu, IDM_COPYCLIP, MF_ENABLED);
  313.             else
  314.             EnableMenuItem(hmenu, IDM_COPYCLIP, MF_DISABLED | MF_GRAYED);
  315.             if (OpenClipboard(hwnd)) {
  316.             if (IsClipboardFormatAvailable(CF_DIB))
  317.                 EnableMenuItem(hmenu, IDM_PASTETO, MF_ENABLED);
  318.             else
  319.                 EnableMenuItem(hmenu, IDM_PASTETO, MF_DISABLED | MF_GRAYED);
  320.             if (IsClipboardFormatAvailable(CF_DIB) || 
  321.                 IsClipboardFormatAvailable(CF_BITMAP)) 
  322.                 EnableMenuItem(hmenu, IDM_CONVERT, MF_ENABLED);
  323.             else
  324.                 EnableMenuItem(hmenu, IDM_CONVERT, MF_DISABLED | MF_GRAYED);
  325.             /* Make EPS sub menu */
  326.             if ((IsClipboardFormatAvailable(CF_DIB) ||
  327.                  IsClipboardFormatAvailable(CF_BITMAP)) 
  328.                 && (doc != (struct document *)NULL) && doc->epsf)
  329.                 EnableMenuItem(hmenuedit, 5, MF_BYPOSITION | MF_ENABLED);
  330.             else
  331.                 EnableMenuItem(hmenuedit, 5, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
  332.             /* Extract EPS sub menu */
  333.             if ( (preview == IDS_EPST) || (preview == IDS_EPSW) )
  334.                 EnableMenuItem(hmenuedit, 6, MF_BYPOSITION | MF_ENABLED);
  335.             else
  336.                 EnableMenuItem(hmenuedit, 6, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
  337.             CloseClipboard();
  338.             }
  339.             return 0;
  340.         }
  341.         break;
  342.     case WM_COMMAND:
  343.         if (LOWORD(wParam) == IDM_DROP) {
  344.             HGLOBAL hglobal;
  345.             char buf[MAXSTR];
  346.             if (lstrlen((LPSTR)lParam) < sizeof(buf))
  347.             lstrcpy(buf, (LPSTR)lParam);
  348.             else
  349.             buf[0] = '\0';
  350.             hglobal = (HGLOBAL)LOWORD(GlobalHandle(SELECTOROF(lParam)));
  351.             GlobalUnlock(hglobal);
  352.             GlobalFree(hglobal);
  353.             if (strnicmp(buf,"/P ",3)==0) {
  354.                 gsview_selectfile(buf+3);
  355.                 gsview_print(FALSE);
  356.             }
  357.             else if (strnicmp(buf,"/F ",3)==0) {
  358.                 gsview_selectfile(buf+3);
  359.                 gsview_print(TRUE);
  360.             }
  361.             else
  362.                 gsview_displayfile(buf);
  363.         }
  364.         else
  365.              gsview_command(LOWORD(wParam));
  366.         return 0;
  367.     case WM_KEYDOWN:
  368.     case WM_KEYUP:
  369.         /* pass on key presses so that child window scroll bars work */
  370.         if (hwndimgchild && IsWindow(hwndimgchild)) {
  371.             SendMessage(hwndimgchild, message, wParam, lParam);
  372.             return 0;
  373.         }
  374.         break;
  375.     case WM_SIZE:
  376.         /* make child window fill client area */
  377.         if (wParam != SIZE_MINIMIZED  && hwndimgchild !=(HWND)NULL && IsWindow(hwndimgchild))
  378.             SetWindowPos(hwndimgchild, (HWND)NULL, img_offset.x, img_offset.y,
  379.             LOWORD(lParam)-img_offset.x, HIWORD(lParam)-img_offset.y, 
  380.             SWP_NOZORDER | SWP_NOACTIVATE);
  381.         /* save window size for INIFILE */
  382.         if (wParam == SIZE_RESTORED) {
  383.             GetWindowRect(hwnd,&rect);
  384.             img_size.x = rect.right-rect.left;
  385.             img_size.y = rect.bottom-rect.top;
  386.         }
  387.         return 0;
  388.     case WM_MOVE:
  389.         /* save window position for INIFILE */
  390.         if (!IsIconic(hwnd) && !IsZoomed(hwnd)) {
  391.             GetWindowRect(hwnd,&rect);
  392.             img_origin.x = rect.left;
  393.             img_origin.y = rect.top;
  394.         }
  395.         return 0;
  396.     case WM_SETCURSOR:
  397.         /* if waiting, display hourglass cursor over our window */
  398.         if (waiting) {
  399.             if (hwndimgchild && IsWindow(hwndimgchild)) {
  400.             if (in_child_client_area() || in_info_area() || (LOWORD(lParam)==HTMENU)) {
  401.                 SetCursor(hcWait);
  402.                 return TRUE;
  403.                 }
  404.             }
  405.             else {
  406.                 SetCursor(hcWait);
  407.                 return TRUE;
  408.             }
  409.         }
  410.         /* track cursor and display coordinates if in child window */
  411.         if (hwndimgchild && IsWindow(hwndimgchild)) {
  412.             if (in_child_client_area() || prev_in_child) {
  413.             /* update coordinate info */
  414.             InvalidateRect(hwndimg, &info_coord, FALSE);
  415.             UpdateWindow(hwndimg);
  416.             }
  417.             prev_in_child = in_child_client_area();
  418.         }
  419.         break;
  420.     case WM_PARENTNOTIFY:
  421.         if (hDlgModeless && (wParam == WM_LBUTTONDOWN))
  422.             if (in_child_client_area())
  423.                 SendMessage(hDlgModeless, WM_COMMAND, BB_CLICK, lParam);
  424.         break;
  425.     case WM_PAINT:
  426.         info_paint(hwnd);
  427.         return 0;
  428.     case WM_MEASUREITEM:
  429.         return 1;
  430.     case WM_DRAWITEM:
  431.         return draw_button((DRAWITEMSTRUCT FAR *)lParam);
  432.     }
  433.     return DefWindowProc(hwnd, message, wParam, lParam);
  434. }
  435.  
  436. /* return TRUE if button drawn */
  437. BOOL
  438. draw_button(DRAWITEMSTRUCT FAR *lpdis)
  439. {
  440. HBRUSH hbrush;
  441. HPEN hpen_highlight, hpen_shadow, hpen_old;
  442. HDC hdc = lpdis->hDC;
  443. RECT rect;
  444. HICON hicon;
  445. HBITMAP hbitmap_old, hbitmap;
  446. BITMAP bm;
  447. int i;
  448. char buf[20];
  449.     rect = lpdis->rcItem;
  450.     if (lpdis->CtlType != ODT_BUTTON)
  451.         return FALSE;
  452.     switch (lpdis->itemAction) {
  453.         case ODA_DRAWENTIRE:
  454.         if ((hbitmap = LoadBitmap(phInstance,MAKEINTRESOURCE(lpdis->CtlID)))
  455.           != (HBITMAP)NULL) {
  456.             HDC hdcsrc = CreateCompatibleDC(hdc);
  457.             hbitmap_old = SelectObject(hdcsrc,hbitmap);
  458.             GetObject(hbitmap, sizeof(BITMAP),&bm);
  459.             if ( (rect.right-rect.left > bm.bmWidth) ||
  460.              (rect.bottom-rect.top > bm.bmHeight) ) {
  461.                 hbrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  462.                 FillRect(hdc, &rect, hbrush);
  463.                 DeleteBrush(hbrush);
  464.             }
  465.             BitBlt(hdc, (rect.left+rect.right-bm.bmWidth)/2,
  466.                (rect.top+rect.bottom-bm.bmHeight)/2,
  467.                bm.bmWidth,bm.bmHeight,hdcsrc,0,0,SRCCOPY);
  468.             SelectObject(hdcsrc,hbitmap_old);
  469.             DeleteObject(hbitmap);
  470.             DeleteDC(hdcsrc);
  471.         }
  472.         else {
  473.             hbrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  474.             FillRect(hdc, &rect, hbrush);
  475.             DeleteBrush(hbrush);
  476.             if ((i = LoadString(phInstance, lpdis->CtlID, buf, sizeof(buf)))
  477.                 != 0) {
  478.             DWORD dw = GetTextExtent(hdc, buf, i);
  479.             SetBkMode(hdc, TRANSPARENT);
  480.             TextOut(hdc, (rect.left+rect.right-LOWORD(dw))/2,
  481.                 (rect.top+rect.bottom-HIWORD(dw))/2, buf, i);
  482.             }
  483.             else if ( (hicon = LoadIcon(phInstance, MAKEINTRESOURCE(lpdis->CtlID)))
  484.                 != (HICON)NULL )  {
  485.                 DrawIcon(hdc, (rect.left+rect.right-32)/2, 
  486.                     (rect.top+rect.bottom-32)/2, hicon);
  487.                 DestroyIcon(hicon);
  488.             }
  489.         }
  490.         hpen_old = SelectPen(hdc, GetStockObject(BLACK_PEN));
  491.         MoveTo(hdc, rect.left, rect.top);
  492.         LineTo(hdc, rect.right-1, rect.top);
  493.         LineTo(hdc, rect.right-1, rect.bottom-1);
  494.         LineTo(hdc, rect.left, rect.bottom-1);
  495.         LineTo(hdc, rect.left, rect.top-1);
  496.         SelectPen(hdc, hpen_old);
  497.         /* fall thru */
  498.         case ODA_FOCUS:
  499.         case ODA_SELECT:
  500.         if (lpdis->itemState & ODS_SELECTED) {
  501.             hpen_highlight = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
  502.             hpen_shadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNFACE));
  503.         }
  504.         else {
  505.             hpen_highlight = CreatePen(PS_SOLID, 1, is_win31 ? GetSysColor(COLOR_BTNHIGHLIGHT) : RGB(255,255,255));
  506.             hpen_shadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
  507.         }
  508.         hpen_old = SelectPen(hdc, hpen_highlight);
  509.         MoveTo(hdc, rect.left+1, rect.bottom-3);
  510.         LineTo(hdc, rect.left+1, rect.top+1);
  511.         LineTo(hdc, rect.right-2, rect.top+1);
  512.         MoveTo(hdc, rect.right-3, rect.top+2);
  513.         LineTo(hdc, rect.left+2, rect.top+2);
  514.         LineTo(hdc, rect.left+2, rect.bottom-4);
  515.         SelectPen(hdc, hpen_shadow);
  516.         MoveTo(hdc, rect.left+1, rect.bottom-2);
  517.         LineTo(hdc, rect.right-2, rect.bottom-2);
  518.         LineTo(hdc, rect.right-2, rect.top+1);
  519.         MoveTo(hdc, rect.right-3, rect.top+2);
  520.         LineTo(hdc, rect.right-3, rect.bottom-3);
  521.         LineTo(hdc, rect.left+2, rect.bottom-3);
  522.         SelectPen(hdc, hpen_old);
  523.         DeleteObject(hpen_highlight);
  524.         DeleteObject(hpen_shadow);
  525.             return TRUE;
  526.     }
  527.     return FALSE;
  528. }
  529.  
  530. /* returns true if cursor in client area of Ghostscript image window */
  531. BOOL
  532. in_child_client_area()
  533. {
  534. RECT rect;
  535. POINT pt;
  536. HWND hwnd;
  537.         GetCursorPos(&pt);
  538.     hwnd = WindowFromPoint(pt);
  539.     if ((hwnd != hwndimg) && !IsChild(hwndimg,hwnd))
  540.         return 0;
  541.         GetClientRect(hwndimgchild, &rect);
  542.         ScreenToClient(hwndimgchild, &pt);
  543.         return PtInRect(&rect, pt);
  544. }
  545.  
  546. /* returns true if cursor in client area of Ghostview window */
  547. BOOL
  548. in_client_area()
  549. {
  550. RECT rect;
  551. POINT pt;
  552. HWND hwnd;
  553.         GetCursorPos(&pt);
  554.     hwnd = WindowFromPoint(pt);
  555.     if ((hwnd != hwndimg) && !IsChild(hwndimg,hwnd))
  556.         return 0;
  557.         GetClientRect(hwndimg, &rect);
  558.         ScreenToClient(hwndimg, &pt);
  559.         return PtInRect(&rect, pt);
  560. }
  561.  
  562. /* returns true if cursor in info area or button area of Ghostview windows */
  563. BOOL
  564. in_info_area()
  565. {
  566. RECT rect;
  567. POINT pt;
  568. HWND hwnd;
  569.         GetCursorPos(&pt);
  570.     hwnd = WindowFromPoint(pt);
  571.     if ((hwnd != hwndimg) && !IsChild(hwndimg,hwnd))
  572.         return 0;
  573.         ScreenToClient(hwndimg, &pt);
  574.  
  575.         GetClientRect(hwndimg, &rect);
  576.     rect.bottom = img_offset.y;
  577.     if (PtInRect(&rect, pt))
  578.         return TRUE;
  579.         GetClientRect(hwndimg, &rect);
  580.     rect.right = img_offset.x;
  581.         return PtInRect(&rect, pt);
  582. }
  583.  
  584. BOOL
  585. get_cursorpos(int *x, int *y)
  586. {
  587. RECT rect;
  588. POINT pt;
  589.     if (hwndimgchild && IsWindow(hwndimgchild)) {
  590.     GetClientRect(hwndimgchild, &rect);
  591.     GetCursorPos(&pt);
  592.     ScreenToClient(hwndimgchild, &pt);
  593.     if (PtInRect(&rect, pt)) {
  594.         *x = (int)((bitmap_scrollx+pt.x)*72.0/xdpi 
  595.         + (epsf_clipped ? doc->boundingbox[LLX] : 0));
  596.         *y = (int)(((bitmap_height-1)-(bitmap_scrolly+pt.y))*72.0/ydpi
  597.         + (epsf_clipped ? doc->boundingbox[LLY] : 0));
  598.         return TRUE;
  599.     }
  600.     }
  601.     return FALSE;
  602. }
  603.  
  604. /* paint brief info area */
  605. void
  606. info_paint(HWND hwnd)
  607. {
  608. HDC hdc;
  609. PAINTSTRUCT ps;
  610. RECT rect;
  611. int i;
  612. char buf[MAXSTR];
  613. char fmt[MAXSTR];
  614. int x, y;
  615.     hdc = BeginPaint(hwnd, &ps);
  616.     SetBkMode(hdc, TRANSPARENT);
  617.     if (info_rect.bottom) {
  618.         GetClientRect(hwnd, &rect);
  619.         rect.top = 0;
  620.         rect.left = info_rect.left;
  621.         rect.bottom = info_rect.bottom;
  622.         FillRect(hdc, &rect, GetStockObject(LTGRAY_BRUSH));
  623.         SelectPen(hdc, GetStockObject(BLACK_PEN));
  624.         MoveTo(hdc, rect.left, rect.bottom);
  625.         LineTo(hdc, rect.right, rect.bottom);
  626.     }
  627.     if (button_rect.right) {
  628.         GetClientRect(hwnd, &rect);
  629.         rect.top = button_rect.top;
  630.         rect.left = button_rect.left;
  631.         rect.right = button_rect.right;
  632.         FillRect(hdc, &rect, GetStockObject(LTGRAY_BRUSH));
  633.         SelectPen(hdc, GetStockObject(BLACK_PEN));
  634.         MoveTo(hdc, rect.right, rect.top);
  635.         LineTo(hdc, rect.right, rect.bottom);
  636.     }
  637.     /* write file information */
  638.     if (dfname[0] != '\0') {
  639.         i = LoadString(phInstance, IDS_FILE, buf, sizeof(buf));
  640.         GetFileTitle(dfname, buf+i, sizeof(buf)-i);
  641.         TextOut(hdc, info_file.x, info_file.y, buf, strlen(buf));
  642.         if (waiting) {
  643.         i = LoadString(phInstance, IDS_WAIT, buf, sizeof(buf));
  644.         TextOut(hdc, info_page.x, info_page.y, buf, strlen(buf));
  645.         }
  646.         else {
  647.           if (doc!=(struct document *)NULL) {
  648.         int n = map_page(pagenum - 1);
  649.         i = LoadString(phInstance, IDS_PAGEINFO, fmt, sizeof(fmt));
  650.         if (doc->pages)
  651.             sprintf(buf, fmt, doc->pages[n].label ? doc->pages[n].label : " ",pagenum,  doc->numpages);
  652.         else
  653.             sprintf(buf, fmt, " " ,pagenum,  doc->numpages);
  654.         TextOut(hdc, info_page.x, info_page.y, buf, strlen(buf));
  655.           }
  656.           else {
  657.         if (is_pipe_done())
  658.             i = LoadString(phInstance, IDS_NOMORE, buf, sizeof(buf));
  659.         else {
  660.             i = LoadString(phInstance, IDS_PAGE, buf, sizeof(buf));
  661.             sprintf(buf+i, "%d", pagenum);
  662.         }
  663.         TextOut(hdc, info_page.x, info_page.y, buf, strlen(buf));
  664.           }
  665.           /* show coordinate */
  666.           if (get_cursorpos(&x, &y)) {
  667.             sprintf(buf,"%d, %d", x, y);
  668.             SetTextAlign(hdc, TA_RIGHT);
  669.             TextOut(hdc, info_coord.right-1, info_coord.top, buf, strlen(buf));
  670.           }
  671.         }
  672.     }
  673.     else {
  674.         i = LoadString(phInstance, IDS_NOFILE, buf, sizeof(buf));
  675.         TextOut(hdc, info_file.x, info_file.y, buf, strlen(buf));
  676.         if (waiting) {
  677.         i = LoadString(phInstance, IDS_WAIT, buf, sizeof(buf));
  678.         TextOut(hdc, info_page.x, info_page.y, buf, strlen(buf));
  679.         }
  680.     }
  681.     EndPaint(hwnd, &ps);
  682. }
  683.  
  684. /* subclass button WndProc to give focus back to parent window */
  685. LRESULT CALLBACK _export
  686. MenuButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  687. {
  688.     switch(message) {
  689.         case WM_LBUTTONUP:
  690.         {
  691.         RECT rect;
  692.         POINT pt;
  693.         GetWindowRect(hwnd, &rect);
  694.         GetCursorPos(&pt);
  695.         if (PtInRect(&rect, pt))
  696.             SendMessage(GetParent(hwnd), WM_COMMAND, GetWindowID(hwnd), 0L);
  697.         SetFocus(GetParent(hwnd));
  698.         }
  699.         break;
  700.     }
  701.     return CallWindowProc(lpfnButtonWndProc, hwnd, message, wParam, lParam);
  702. }
  703.  
  704.  
  705. void
  706. play_sound(int num)
  707. {
  708.     if (strlen(sound[num].file)==0)
  709.         return;
  710.     if (!is_win31 || (strcmp(sound[num].file,BEEP)==0)) {
  711.         MessageBeep(-1);
  712.         return;
  713.     }
  714.     if (is_win31) {
  715.         if (lpfnSndPlaySound != (FPSPS)NULL) 
  716.                lpfnSndPlaySound(sound[num].file, SND_SYNC);
  717.         else
  718.             MessageBeep(-1);
  719.         return;
  720.     }
  721. }
  722.  
  723. BOOL
  724. set_timer(UINT period)
  725. {
  726.     timeout_count = period;
  727.     bTimeout = FALSE;
  728.     if (SetTimer(hwndimg, ID_MYTIMER, 1000, NULL) != 0) {
  729.         bTimerSet = TRUE;
  730.         return TRUE;
  731.     }
  732.  
  733.     bTimerSet = FALSE;
  734.     gserror(IDS_NOTIMER, NULL, MB_ICONINFORMATION, SOUND_TIMEOUT);
  735.     return FALSE;
  736. }
  737.  
  738. void
  739. clear_timer()
  740. {
  741.     if (bTimerSet)
  742.         KillTimer(hwndimg, ID_MYTIMER);
  743.     bTimerSet = FALSE;
  744.     bTimeout = FALSE;
  745.     EnableWindow(hwndimg, TRUE);
  746. }
  747.  
  748. /* display or remove 'wait' message */
  749. void
  750. info_wait(BOOL wait)
  751. {
  752. HWND hwnd;
  753. POINT pt;
  754.     waiting = wait;
  755.     InvalidateRect(hwndimg, (LPRECT)&info_rect, FALSE);
  756.     UpdateWindow(hwndimg);
  757.  
  758.     if (waiting) {
  759.             GetCursorPos(&pt);
  760.         hwnd = WindowFromPoint(pt);
  761.         if ((hwnd == hwndimg) || IsChild(hwndimg,hwnd))
  762.         SetCursor(hcWait);
  763.     }
  764.     else {
  765.         /* set cursor to that of active window */
  766.         hwnd = GetFocus();
  767.         if ( (hwndimgchild && IsWindow(hwndimgchild))
  768.           && ((hwnd == hwndimg) || (hwnd == hwndimgchild)) ) {
  769.         if (in_child_client_area()) {
  770.             SetCursor(GetClassCursor(hwndimgchild));
  771.             return;
  772.         }
  773.         }
  774.         SetCursor(GetClassCursor(hwnd));
  775.     }
  776. }
  777.  
  778.  
  779. /* remove temporary files etc. */
  780. void
  781. gsview_close()
  782. {
  783.     gswin_close();
  784.     pipeclose();
  785.     print_cleanup();
  786.     if ((efname[0] != '\0') && !debug)
  787.         unlink(efname);
  788.     efname[0] = '\0';
  789.     if (page_list.select)
  790.         free(page_list.select);
  791.     page_list.select = NULL;
  792.     if (doc)
  793.         psfree(doc);
  794.     doc = (struct document *)NULL;
  795.     if (settings)
  796.         write_profile();
  797.     SetCursor(GetClassCursor((HWND)NULL));
  798.     return;
  799. }
  800.  
  801.  
  802. /* gsview menu commands */
  803. int
  804. gsview_command(WORD command)
  805. {
  806. char prompt[MAXSTR];        /* input dialog box prompt and message box string */
  807. char answer[MAXSTR];        /* input dialog box answer string */
  808.     if (hDlgModeless) {
  809.     play_sound(SOUND_ERROR);
  810.     return 0;    /* obtaining Bounding Box so ignore commands */
  811.     }
  812.     if (waiting) {
  813.     /* if user impatient or gsview confused */
  814.     LoadString(phInstance, IDS_BUSY, prompt, sizeof(prompt));
  815.     if (MessageBox(hwndimg, prompt, szAppName, MB_YESNO | MB_ICONQUESTION) == IDYES) {
  816.         play_sound(SOUND_ERROR);
  817.         next_page();
  818.         info_wait(FALSE);
  819.     }
  820.     return 0;
  821.     }
  822.     switch (command) {
  823.     case IDM_OPEN:
  824.         dfreopen();
  825.         gsview_display();
  826.         dfclose();
  827.         return 0;
  828.     case IDM_CLOSE:
  829.         dfreopen();
  830.         gsview_endfile();
  831.         dfname[0] = '\0';
  832.         dfclose();
  833.         if (page_list.select)
  834.             free(page_list.select);
  835.         page_list.select = NULL;
  836.         if (doc)
  837.             psfree(doc);
  838.         doc = (struct document *)NULL;
  839.             if (gswin_hinst != (HINSTANCE)NULL) {
  840.                 fprintf(cfile,"erasepage flushpage\r\n");
  841.                 set_timer(timeout);
  842.                 pipeflush();
  843.             }
  844.         info_wait(FALSE);
  845.         return 0;
  846.     case IDM_NEXT:
  847.         if (not_open())
  848.             return 0;
  849.         info_wait(TRUE);
  850.         if (doc==(struct document *)NULL) {
  851.             if (!gswin_open())
  852.                 return 0;
  853.             if (is_pipe_done()) {
  854.             play_sound(SOUND_NOPAGE);
  855.             info_wait(FALSE);
  856.             }
  857.             else {
  858.             pagenum++;
  859.             next_page();
  860.             }
  861.             return 0;
  862.         }
  863.         dfreopen();
  864.         dsc_next(1);
  865.         dfclose();
  866.         return 0;
  867.     case IDM_NEXTSKIP:
  868.         if (not_dsc())
  869.             return 0;
  870.         dfreopen();
  871.         dsc_next(page_skip);
  872.         dfclose();
  873.         return 0;
  874.     case IDM_REDISPLAY:
  875.         if (not_open())
  876.             return 0;
  877.         info_wait(TRUE);
  878.         if (doc==(struct document *)NULL) {
  879.             /* don't know where we are so close and reopen */
  880.             if (!is_pipe_done())
  881.             gswin_close();
  882.         }
  883.         if (!gswin_open())
  884.             return 0;
  885.         info_wait(TRUE);
  886.         if (page_ready)
  887.             next_page(); 
  888.         dfreopen();
  889.         if ((doc==(struct document *)NULL) || (doc->pages==0)) {
  890.             gsview_displayfile(dfname);
  891.             dfclose();
  892.             return 0;
  893.         }
  894.         dsc_dopage();
  895.         dfclose();
  896.         return 0;
  897.     case IDM_PREV:
  898.         if (not_dsc())
  899.             return 0;
  900.         dfreopen();
  901.         dsc_prev(1);
  902.         dfclose();
  903.         return 0;
  904.     case IDM_PREVSKIP:
  905.         if (not_dsc())
  906.             return 0;
  907.         dfreopen();
  908.         dsc_prev(page_skip);
  909.         dfclose();
  910.         return 0;
  911.     case IDM_GOTO:
  912.         if (not_dsc())
  913.             return 0;
  914.         dfreopen();
  915.         if (doc->numpages == 0) {
  916.             gserror(IDS_NOPAGE, NULL, MB_ICONEXCLAMATION, SOUND_NONUMBER);
  917.         }
  918.         else if (get_page(&pagenum, FALSE)) {
  919.             if (pagenum > doc->numpages) {
  920.             pagenum = doc->numpages;
  921.             play_sound(SOUND_NOPAGE);
  922.             }
  923.             else if (pagenum < 1) {
  924.             pagenum = 1;
  925.             play_sound(SOUND_NOPAGE);
  926.             }
  927.             else {
  928.             if (gswin_open()) {
  929.                 info_wait(TRUE);
  930.                 if (page_ready)
  931.                     next_page();
  932.                 dsc_dopage();
  933.             }
  934.             }
  935.         }
  936.         dfclose();
  937.         return 0;
  938.     case IDM_INFO:
  939.         {
  940.         DLGPROC lpProcInfo;
  941.         lpProcInfo = (DLGPROC)MakeProcInstance((FARPROC)InfoDlgProc, phInstance);
  942.         DialogBoxParam( phInstance, "InfoDlgBox", hwndimg, lpProcInfo, (LPARAM)NULL);
  943.         FreeProcInstance((FARPROC)lpProcInfo);
  944.         }
  945.         return 0;
  946.     case IDM_SELECT:
  947.         gsview_select();
  948.         dfclose();
  949.         return 0;
  950.     case IDM_PRINT:
  951.         if (dfname[0] == '\0')
  952.             gsview_select();
  953.         dfreopen();
  954.         if (dfname[0] != '\0')
  955.             gsview_print(FALSE);
  956.         dfclose();
  957.         return 0;
  958.     case IDM_PRINTTOFILE:
  959.         if (dfname[0] == '\0')
  960.             gsview_select();
  961.         dfreopen();
  962.         if (dfname[0] != '\0')
  963.             gsview_print(TRUE);
  964.         dfclose();
  965.         return 0;
  966.     case IDM_SPOOL:
  967.         gsview_spool();
  968.         return 0;
  969.     case IDM_EXTRACT:
  970.         if (dfname[0] == '\0')
  971.             gsview_select();
  972.         dfreopen();
  973.         if (dfname[0] != '\0')
  974.             gsview_extract();
  975.         dfclose();
  976.         return 0;
  977.     case IDM_EXIT:
  978.         PostQuitMessage(0);
  979.         return 0;
  980.     case IDM_COPYCLIP:
  981.         if (hwndimgchild && IsWindow(hwndimgchild))
  982.             SendMessage(hwndimgchild, WM_GSVIEW, COPY_CLIPBOARD, NULL);
  983.         return 0;
  984.     case IDM_PASTETO:
  985.         clip_to_file();
  986.         return 0;
  987.     case IDM_CONVERT:
  988.         clip_convert();
  989.         return 0;
  990.     case IDM_GSCOMMAND:
  991.         LoadString(phInstance, IDS_GSCOMMAND, prompt, sizeof(prompt));
  992.         strcpy(answer, szGSwin);
  993.         LoadString(phInstance, IDS_TOPICGSCMD, szHelpTopic, sizeof(szHelpTopic));
  994.         if (get_string(prompt,answer))
  995.             strcpy(szGSwin, answer);
  996.         if (szGSwin[0]=='\0')
  997.             strcpy(szGSwin, DEFAULT_GSCOMMAND);
  998.         return 0;
  999.     case IDM_SAVEDIR:
  1000.         save_dir = !save_dir;
  1001.         CheckMenuItem(hmenu, IDM_SAVEDIR, MF_BYCOMMAND | 
  1002.             (save_dir ? MF_CHECKED : MF_UNCHECKED));
  1003.         return 0;
  1004.     case IDM_BUTTONSHOW:
  1005.         button_show = !button_show;
  1006.         CheckMenuItem(hmenu, IDM_BUTTONSHOW, MF_BYCOMMAND | 
  1007.             (button_show ? MF_CHECKED : MF_UNCHECKED));
  1008.         show_buttons();
  1009.         return 0;
  1010.     case IDM_QUICK:
  1011.         quick = !quick;
  1012.         CheckMenuItem(hmenu, IDM_QUICK, MF_BYCOMMAND | 
  1013.             (quick ? MF_CHECKED : MF_UNCHECKED));
  1014.         return 0;
  1015.     case IDM_AUTOREDISPLAY:
  1016.         redisplay = !redisplay;
  1017.         CheckMenuItem(hmenu, IDM_AUTOREDISPLAY, MF_BYCOMMAND | 
  1018.             (redisplay ? MF_CHECKED : MF_UNCHECKED));
  1019.         return 0;
  1020.     case IDM_EPSFCLIP:
  1021.         epsf_clip = !epsf_clip;
  1022.         CheckMenuItem(hmenu, IDM_EPSFCLIP, MF_BYCOMMAND | 
  1023.             (epsf_clip ? MF_CHECKED : MF_UNCHECKED));
  1024.         gswin_resize();
  1025.         return 0;
  1026.     case IDM_EPSFWARN:
  1027.         epsf_warn = !epsf_warn;
  1028.         CheckMenuItem(hmenu, IDM_EPSFWARN, MF_BYCOMMAND | 
  1029.             (epsf_warn ? MF_CHECKED : MF_UNCHECKED));
  1030.         return 0;
  1031.     case IDM_PSTOEPS:
  1032.         if (dfname[0] == '\0')
  1033.             gsview_display();
  1034.         if (dfname[0] != '\0') {
  1035.             dfreopen();
  1036.             ps_to_eps();
  1037.             dfclose();
  1038.         }
  1039.         return 0;
  1040.     case IDM_MAKEEPSI:
  1041.         dfreopen();
  1042.         make_eps_interchange();
  1043.         dfclose();
  1044.         return 0;
  1045.     case IDM_MAKEEPST4:
  1046.     case IDM_MAKEEPST:
  1047.         dfreopen();
  1048.         make_eps_tiff(command);
  1049.         dfclose();
  1050.         return 0;
  1051.     case IDM_MAKEEPSW:
  1052.         dfreopen();
  1053.         make_eps_metafile();
  1054.         dfclose();
  1055.         return 0;
  1056.     case IDM_EXTRACTPS:
  1057.     case IDM_EXTRACTPRE:
  1058.         dfreopen();
  1059.         extract_doseps(command);
  1060.         dfclose();
  1061.         return 0;
  1062.     case IDM_SETTINGS:
  1063.         write_profile();
  1064.         return 0;
  1065.     case IDM_SAVESETTINGS:
  1066.         if (settings) 
  1067.             CheckMenuItem(hmenu, IDM_SAVESETTINGS, MF_BYCOMMAND | MF_UNCHECKED);
  1068.         else
  1069.             CheckMenuItem(hmenu, IDM_SAVESETTINGS, MF_BYCOMMAND | MF_CHECKED);
  1070.         settings = !settings;
  1071.         sprintf(prompt, "%d", settings);
  1072.         WritePrivateProfileString(INISECTION, "SaveSettings", prompt, INIFILE);
  1073.         return 0;
  1074.     case IDM_SOUNDS:
  1075.         {
  1076.         DLGPROC lpProcSound;
  1077.         LoadString(phInstance, IDS_TOPICSOUND, szHelpTopic, sizeof(szHelpTopic));
  1078.         lpProcSound = (DLGPROC)MakeProcInstance((FARPROC)SoundDlgProc, phInstance);
  1079.         DialogBoxParam( phInstance, "SoundDlgBox", hwndimg, lpProcSound, (LPARAM)NULL);
  1080.         FreeProcInstance((FARPROC)lpProcSound);
  1081.         }
  1082.         return 0;
  1083.     case IDM_PORTRAIT:
  1084.     case IDM_LANDSCAPE:
  1085.     case IDM_UPSIDEDOWN:
  1086.     case IDM_SEASCAPE:
  1087.     case IDM_SWAPLANDSCAPE:
  1088.         dfreopen();
  1089.         gsview_orientation(command);
  1090.         dfclose();
  1091.         return 0;
  1092.     case IDM_RESOLUTION:
  1093.         LoadString(phInstance, IDS_RES, prompt, sizeof(prompt));
  1094.         if (xdpi == ydpi)
  1095.             sprintf(answer,"%g", xdpi);
  1096.         else 
  1097.             sprintf(answer,"%g %g", xdpi, ydpi);
  1098.         LoadString(phInstance, IDS_TOPICMEDIA, szHelpTopic, sizeof(szHelpTopic));
  1099.         if (get_string(prompt,answer)) {
  1100.             switch (sscanf(answer,"%f %f", &xdpi, &ydpi)) {
  1101.               case EOF:
  1102.               case 0:
  1103.             return 0;
  1104.               case 1:
  1105.             ydpi = xdpi;
  1106.               case 2:
  1107.             if (xdpi==0.0)
  1108.                 xdpi = DEFAULT_RESOLUTION;
  1109.             if (ydpi==0.0)
  1110.                 ydpi = DEFAULT_RESOLUTION;
  1111.             dfreopen();
  1112.             gswin_resize();
  1113.             dfclose();
  1114.             }
  1115.         }
  1116.         return 0;
  1117.     case IDM_LETTER:
  1118.     case IDM_LETTERSMALL:
  1119.     case IDM_TABLOID:
  1120.     case IDM_LEDGER:
  1121.     case IDM_LEGAL:
  1122.     case IDM_STATEMENT:
  1123.     case IDM_EXECUTIVE:
  1124.     case IDM_A3:
  1125.     case IDM_A4:
  1126.     case IDM_A4SMALL:
  1127.     case IDM_A5:
  1128.     case IDM_B4:
  1129.     case IDM_B5:
  1130.     case IDM_FOLIO:
  1131.     case IDM_QUARTO:
  1132.     case IDM_10X14:
  1133.     case IDM_USERSIZE:
  1134.         if (command == IDM_USERSIZE)
  1135.             if (!gsview_usersize())
  1136.             return 0;
  1137.         dfreopen();
  1138.         gsview_media(command);
  1139.         dfclose();
  1140.         return 0;
  1141.     case IDM_HELPCONTENT:
  1142.         WinHelp(hwndimg,szHelpName,HELP_CONTENTS,(DWORD)NULL);
  1143.         return 0;
  1144.     case IDM_HELPSEARCH:
  1145.         WinHelp(hwndimg,szHelpName,HELP_PARTIALKEY,(DWORD)"");
  1146.         return 0;
  1147.     case IDM_ABOUT:
  1148.         {
  1149.         DLGPROC lpProcAbout;
  1150.         lpProcAbout = (DLGPROC)MakeProcInstance((FARPROC)AboutDlgProc, phInstance);
  1151.         DialogBoxParam( phInstance, "AboutDlgBox", hwndimg, lpProcAbout, (LPARAM)NULL);
  1152.         FreeProcInstance((FARPROC)lpProcAbout);
  1153.         }
  1154.         return 0;
  1155.     }
  1156.     return 0;
  1157. }
  1158.  
  1159. /* if no document open, display error message and return true */
  1160. BOOL
  1161. not_open()
  1162. {
  1163.     if (dfname[0] != '\0')
  1164.         return FALSE;
  1165.     gserror(IDS_NOTOPEN, NULL, MB_ICONEXCLAMATION, SOUND_NOTOPEN);
  1166.     return TRUE;
  1167. }
  1168.  
  1169. /* if not DSC document or not open, display error message and return true */
  1170. BOOL
  1171. not_dsc()
  1172. {
  1173.     if (not_open())
  1174.         return TRUE;
  1175.     if (doc!=(struct document *)NULL)
  1176.         return FALSE;
  1177.     gserror(IDS_NOPAGE, NULL, MB_ICONEXCLAMATION, SOUND_NONUMBER);
  1178.     return TRUE;
  1179. }
  1180.  
  1181. void
  1182. gserror(UINT id, char *str, UINT icon, int sound)
  1183. {
  1184. int i;
  1185. char mess[300];
  1186.     if (sound >= 0)
  1187.         play_sound(sound);
  1188.     i = 0;
  1189.     if (id)
  1190.         i = LoadString(phInstance, id, mess, sizeof(mess)-1);
  1191.     mess[i] = '\0';
  1192.     if (str)
  1193.         strncpy(mess+i, str, sizeof(mess)-i-1);
  1194.     MessageBox(hwndimg, mess, szAppName, icon | MB_OK);
  1195. }
  1196.  
  1197. /* for ps.c errors instead of fprintf(stderr,...)! */
  1198. void
  1199. pserror(char *str)
  1200. {
  1201.     MessageBox(hwndimg,str,szAppName, MB_OK | MB_ICONHAND);
  1202. }
  1203.